﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEditor;
using UnityEngine.SceneManagement;

namespace Nirvana
{
    [Serializable]
    public sealed class AssetCheckReportItem
    {
        public enum ServerityType
        {
            Warn,
            Error
        }

        /// <summary>
        /// 严重性提示颜色
        /// </summary>
        [SerializeField]
        private ServerityType mServerity;

        [SerializeField]
        private string mAssetGUID;
        [SerializeField]
        private string mObjectName;
        [SerializeField]
        private string mHierarchyPath;
        [SerializeField]
        private string mMessage;

        public ServerityType Serverity
        {
            get { return mServerity; }
            set { mServerity = value; }
        }

        public string AssetGUID
        {
            get { return mAssetGUID; }
            set { mAssetGUID = value; }
        }

        public string ObjectName
        {
            get { return mObjectName; }
            set { mObjectName = value; }
        }

        public string HierarchyPath
        {
            get { return mHierarchyPath; }
            set { mHierarchyPath = value; }
        }

        public string Message
        {
            get { return mMessage; }
            set { mMessage = value; }   
        }

        public string AssetPath
        {
            get { return AssetDatabase.GUIDToAssetPath(this.mAssetGUID); }
        }

        public UnityEngine.Object Object
        {
            get { return AssetDatabase.LoadAssetAtPath(this.AssetPath, typeof(UnityEngine.Object)); }
        }

        public static void Show(List<AssetCheckReportItem> itemlist,ref Vector2 pos,ref int index)
        {
            var itemui = new ReportItemUI();
            itemui.curIndex = index;

            pos = GUILayoutEx.ScrollViewFixHeight<AssetCheckReportItem>(pos, itemlist, 1.75f * EditorGUIUtility.singleLineHeight, 600,itemui.Draw);
            index = itemui.curIndex;
        }

        private int Draw(int curIndex, int startIndex)
        {
            if(curIndex == startIndex)
            {
                GUILayout.BeginHorizontal(AssetCheckReportItemGUIStyle.Gray,
                    GUILayout.MinHeight(1.75f * EditorGUIUtility.singleLineHeight),
                    GUILayout.MaxHeight(1.75f * EditorGUIUtility.singleLineHeight)
                );
            }
            else
            {
                bool flag = curIndex % 2 == 0;
                GUILayout.BeginHorizontal(!flag ? AssetCheckReportItemGUIStyle.Gray03 : AssetCheckReportItemGUIStyle.Gray02,
                    GUILayout.MinHeight(1.75f * EditorGUIUtility.singleLineHeight),
                    GUILayout.MaxHeight(1.75f * EditorGUIUtility.singleLineHeight)
                );

            }

            if(this.mServerity == ServerityType.Error)
            {
                GUILayout.Label(AssetCheckReportItemGUIStyle.errorSml, GUILayout.ExpandWidth(false));
            }
            else
            {
                GUILayout.Label(AssetCheckReportItemGUIStyle.warnSml, GUILayout.ExpandWidth(true));
            }

            string msg = string.Format("{0}:\n{1}", this.AssetPath, this.mMessage);

            if(GUILayout.Button(msg, AssetCheckReportItemGUIStyle.richText, GUILayout.ExpandHeight(true)))
            {
                startIndex = curIndex;
                if (!IsSelect())
                {
                    EditorGUIUtility.PingObject(this.Object);
                }
            }

            GUILayout.EndHorizontal();
            return startIndex;
        }

        private bool IsSelect()
        {
            if (this.mHierarchyPath == null) return false;

            GameObject obj = this.Object as GameObject;
            if (obj == null) return false;
            Transform trans = obj.transform.FindHard(this.mHierarchyPath);
            if (trans == null) return false;

            GameObject[] objs = SceneManager.GetActiveScene().GetRootGameObjects();
            foreach(var g in objs)
            {
                var prefabType = PrefabUtility.GetPrefabAssetType(g);
                if(prefabType == PrefabAssetType.Regular)
                {
                    var p = PrefabUtility.GetCorrespondingObjectFromSource(g);
                    if(p == obj)
                    {
                        string path;
                        if(DictionaryTool.IsExist(obj.transform,trans.gameObject,out path))
                        {
                            var t = g.transform.FindHard(path);
                            if(t != null)
                            {
                                EditorGUIUtility.PingObject(t);
                                return true;
                            }
                        }
                    }

                }
            }
            return false;
        }

        private static class AssetCheckReportItemGUIStyle
        {
            public static GUIStyle Gray, Gray03, Gray02, richText;
            public static GUIContent warnSml, errorSml;
            static AssetCheckReportItemGUIStyle()
            {
                Gray = new GUIStyle { border = new RectOffset(0, 0, 0, 0) };
                Gray.normal.background = TextureMaker.Monochromatic(new Color(0.1f,0.1f,0.35f));
                Gray03 = new GUIStyle { border = new RectOffset(0, 0, 0, 0) };
                Gray03.normal.background = TextureMaker.Gray(0.3f);
                Gray02 = new GUIStyle { border = new RectOffset(0, 0, 0, 0) };
                Gray02.normal.background = TextureMaker.Gray(0.2f);

                richText = new GUIStyle { richText = true };
                richText.normal.textColor = new Color(0.75f, 0.75f, 0.75f, 1f);

                warnSml = EditorGUIUtility.IconContent("console.warnicon.sml");
                errorSml = EditorGUIUtility.IconContent("console.erroricon.sml");
            }
        }

        private sealed class ReportItemUI
        {
            public int curIndex;
            public void Draw(AssetCheckReportItem item, int startIndex)
            {
                this.curIndex = item.Draw(startIndex, this.curIndex);
            }
        }

    }
}

